In computer systems, the term “resource” typically refers to non-code content. Examples of resources include text, images, audio, video, etc. In some cases, multiple versions of a particular resource may exist. The different versions may be interchangeable, depending on one or more conditions. For example, localization is the process of supplying different versions of an application to users who speak different languages. A particular application may have an English version, a French version, etc. Accordingly, one version of a resource may include application text in English, another version of the resource may include application text in French, etc. As another example, an application may have different versions of resources that are used depending on a non-language-related user preference, such as a parental control setting in a videogame. As another example, an application may have different versions of resources depending on the user's application licensing status (e.g., free, open source, trial, paid, premium, etc.), such as different lists of application features that are available to the user under the current license. Many different situations exist where different versions of resources may be used.
Different versions of resources may be supported in many different ways. Different versions of properties files may be used to store and retrieve different versions of resources. For example, in a Java environment, properties files may be stored and/or opened using objects of type “java.util.ResourceBundle” or “java.util.PropertyResourceBundle.” A predetermined key may be used to look up a corresponding property. For example, performing a property lookup using a key called “greeting” may return the word “hello” in an English version and “bonjour” in a French version. Alternatively or in addition, location-independent resource lookup may be supported. For example, in a Java environment, a “ClassLoader::getResource(r)” method call may be used to locate the resource bundle on the classpath, where r is the name of a specific version of the resource. The application code performing the lookup needs to know the name of the resource but not its specific location.
Different versions of a resource may be stored in different locations. In a module system, different versions may be stored in different modules. For example, in a Java-based module system, a module may be represented as a Java archive file (JAR). Each JAR may correspond to a single module, which may be referred to as a modular JAR. The module system may also include a separate module with the main application code. Thus, for a hypothetical application with both English and German versions, there may be a module with the main application code (e.g., “main.jar”), a module with English-language resources (e.g., “app.en.jar”), and a module with German-language resources (e.g., “app.de.jar”). Separating different versions of resources into different modules and/or JARs may allow application developers to more readily add or modify versions without affecting other versions.
Even if different versions of resources are stored in separate modules, the different versions may be associated with (e.g., declared as belonging to) the same package. For example, in a Java environment, “com.oracle.weblogic.en” and “com.oracle.weblogic.de” both are in the “com.oracle.weblogic” package. In other words, packages of the same name are found in different modules. A situation where packages of the same name are found in different modules may be referred to as a “split package.” A split package may be a security concern. For example, objects of different classes, in packages of the same name, may be permitted to read each other at compile-time and/or runtime. Thus, code or resources that were not intended to be read by other modules may nonetheless be accessible by other modules. Alternatively or in addition, a split package may affect system stability by increasing the possibility of runtime errors and/or unpredictable application behavior. For example, one module may include an old version of a particular class file, and another module may include a newer version of the same class file, both versions being associated with the same package name. If both modules are allowed in the module system simultaneously, it may be difficult or impossible to know which version is being used at runtime, resulting in unstable system performance.
Because of security and/or stability concerns such as those discussed above, a module system may require that a particular package name be used in only a single module (e.g., a single modular JAR). This restriction may help avoid code conflicts and/or inadvertent code leakage. However, as discussed above, an application developer may attempt to store different versions of resources in different modules, associated with the same package name. Thus, a module system that categorically prohibits split modules may not support the application developer's preferred approach to organizing code and resources.
To allow for different modules associated with the same package name, a module system may support different types of modules and/or module component, with one or more types of modules/components allowing split packages and one or more other types of modules/components not allowing split packages. For example, Open Service Gateway Initiative (OSGi) supports host bundles and fragment bundles, underneath a module layer. However, supporting different types of modules requires the application developer(s) to keep track of the types of each module, as well as the rules surrounding the use of each type of module and the relationships between different types of modules.
The approaches described in this section are approaches that could be pursued, but not necessarily approaches that have been previously conceived or pursued. Therefore, unless otherwise indicated, it should not be assumed that any of the approaches described in this section qualify as prior art merely by virtue of their inclusion in this section.